//! 声明宏 (Declarative Macros)
//!
//! 声明宏使用`macro_rules!`定义，是 Rust 中创建 DSL（领域特定语言）的主要方式。
//! 它们在编译时展开，允许编写类似函数的代码，但具有更强大的元编程能力。
//!
//! ## 知识点总结
//!
//! | 知识点 | 说明 |
//! |--------|------|
//! | 宏定义 | 使用`macro_rules!`定义声明宏 |
//! | 宏调用 | 使用`!`调用宏，如`println!()` |
//! | 设计符 | `$expr`、`$ident`等用于匹配不同类型代码片段 |
//! | 重复匹配 | 使用`$(...)*`或`$(...)+`匹配重复代码 |
//! | 卫生性 | 宏展开时会保持变量作用域的正确性 |
//!
//! ## 声明宏设计符详细说明和用法示例
//!
//! | 指示符 | 类型 | 用途 | 用法示例 |
//! |--------|------|------|----------|
//! | `$ident` | 标识符 | 匹配一个标识符（例如变量名或函数名） | `macro_rules! m { ($i:ident) => { let $i = 1; } }` |
//! | `$expr` | 表达式 | 匹配任意表达式 | `macro_rules! m { ($e:expr) => { println!("{:?}", $e); } }` |
//! | `$stmt` | 语句 | 匹配任意语句 | `macro_rules! m { ($s:stmt) => { $s; } }` |
//! | `$ty` | 类型 | 匹配任意类型 | `macro_rules! m { ($t:ty) => { let x: $t = Default::default(); } }` |
//! | `$pat` | 模式 | 匹配任意模式（例如函数参数） | `macro_rules! m { ($p:pat) => { let $p = 1; } }` |
//! | `$path` | 路径 | 匹配模块路径或类型路径 | `macro_rules! m { ($p:path) => { let x = $p::new(); } }` |
//! | `$item` | 项 | 匹配任意项（例如函数、结构体、枚举等） | `macro_rules! m { ($i:item) => { $i } }` |
//! | `$vis` | 可见性 | 匹配可见性修饰符（例如 `pub` 或 `crate`） | `macro_rules! m { ($v:vis struct $n:ident;) => { $v struct $n; } }` |
//! | `$lifetime` | 生命周期 | 匹配生命周期标识符 | `macro_rules! m { ($l:lifetime) => { let x: &$l str = "hello"; } }` |
//! | `$tt` | 令牌树 | 匹配任意令牌树，可以包含多个令牌 | `macro_rules! m { ($t:tt) => { println!("{:?}", $t); } }` |
//! | `$crate` | 特殊路径 | 匹配当前 crate 的路径 | `macro_rules! m { () => { $crate::some_function() } }` |
//! | `$block` | 块 | 匹配代码块 `{ ... }` | `macro_rules! m { ($b:block) => { $b } }` |
//! | `$meta` | 元数据 | 匹配元数据（例如属性） | `macro_rules! m { ($m:meta) => { #[$m] fn f() {} } }` |
//! | `$literal` | 字面量 | 匹配字面量（例如 `42` 或 `"hello"`） | `macro_rules! m { ($l:literal) => { println!("{}", $l); } }` |
//!
//! ## 声明宏与过程宏对比表
//!
//! | 特性 | 声明宏 | 过程宏 |
//! |------|--------|--------|
//! | 定义方式 | `macro_rules!` | 函数式、派生式、属性式 |
//! | 执行时机 | 编译时 | 编译时 |
//! | 输入输出 | 令牌树 -> 令牌树 | TokenStream -> TokenStream |
//! | 复杂度 | 相对简单 | 相对复杂 |
//! | 学习曲线 | 较平缓 | 较陡峭 |
//! | 使用场景 | 简单代码生成 | 复杂代码生成 |
//! | 性能 | 较快 | 较慢 |
//! | 错误处理 | 有限 | 灵活 |
//! | 调试 | 困难 | 相对容易 |
//! | 可应用目标 | 表达式、语句、项等 | 取决于宏类型 |
//! | 派生宏限制 | 不适用 | 只能用于结构体和枚举 |
//! | 属性宏限制 | 不适用 | 可用于函数、结构体、模块等 |
//! | 函数式宏限制 | 不适用 | 可用于标识符 |

/// 1. 基础声明宏
/// 使用 macro_rules! 定义一个简单的声明宏
macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

/// 2. 带参数的声明宏
/// 声明宏可以接受参数，就像函数一样
macro_rules! greet {
    ($name:expr) => {
        println!("Hello, {name}!", name = $name);
    };
}

/// 3. 多个匹配臂的声明宏
/// 声明宏可以有多个匹配臂，类似于 match 表达式
macro_rules! create_function {
    ($func_name:ident) => {
        fn $func_name() {
            println!("你调用了 {:?}()", stringify!($func_name));
        }
    };
}

/// 4. 重复模式的声明宏
/// 声明宏可以处理可变数量的参数
macro_rules! vec_with_repeat {
    ($($x:expr),*) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

/// 5. 复杂的声明宏示例
/// 创建一个类似于 println! 的宏
macro_rules! my_println {
    () => {
        println!("");
    };
    ($($arg:tt)*) => {
        println!($($arg)*);
    };
}

/// 6. 不同类型参数的声明宏
/// 声明宏可以处理不同类型的参数
macro_rules! my_assert_equal {
    ($left:expr, $right:expr) => {{
        let left_val = $left;
        let right_val = $right;
        if !(&left_val == &right_val) {
            panic!(
                "断言失败: `{}` != `{}`\n\
                     左值: `{:?}`,\n\
                     右值: `{:?}`",
                stringify!($left),
                stringify!($right),
                left_val,
                right_val
            );
        }
    }};
}

/// 7. DSL (领域特定语言) 示例
/// 声明宏可以用来创建小型的领域特定语言
macro_rules! calculate {
    (eval $e:expr) => {
        {
            let val: usize = $e;
            println!("{} = {val}", stringify!{$e});
        }
    };
}

/// 8. 各种宏指示符的详细用法示例
/// 下面是一些使用不同宏指示符的具体示例：
/// 使用 `$ident` 匹配标识符
macro_rules! create_variable {
    ($name:ident, $value:expr) => {
        let $name = $value;
        println!("创建变量 {name}: {name:?}", name = stringify!($name));
    };
}

/// 使用 `$ty` 匹配类型
macro_rules! default_value {
    ($t:ty) => {{
        let val: $t = Default::default();
        println!("{} 的默认值: {val:?}", stringify!($t));
        val
    }};
}

/// 使用 `$pat` 匹配模式
macro_rules! match_pattern {
    ($val:expr, $pat:pat) => {
        match $val {
            $pat => println!("匹配成功"),
            _ => println!("匹配失败"),
        }
    };
}

/// 使用 `$path` 匹配路径
macro_rules! call_function {
    ($path:path) => {{
        let result = $path();
        println!("调用函数 {path:?} 的结果: {result:?}", path = stringify!($path));
    }};
}

/// 使用 `$item` 匹配项
macro_rules! define_item {
    ($item:item) => {
        $item
    };
}

/// 使用 `$vis` 匹配可见性
macro_rules! define_struct_with_visibility {
    ($vis:vis $name:ident { $($field_vis:vis $field:ident: $ty:ty),* }) => {
        $vis struct $name {
            $($field_vis $field: $ty),*
        }
    };
}

/// 使用 `$lifetime` 匹配生命周期
macro_rules! with_lifetime {
    ($lt:lifetime, $t:ty) => {
        fn with_lifetime_fn<$lt>(x: &$lt $t) -> &$lt $t {
            x
        }
    };
}

/// 使用 `$tt` 匹配令牌树
macro_rules! echo_tokens {
    ($($t:tt)*) => {
        println!("令牌: {}", stringify!($($t)*));
    };
}

/// 使用 `$block` 匹配代码块
macro_rules! time_block {
    ($block:block) => {
        {
            let start = std::time::Instant::now();
            $block
            let duration = start.elapsed();
            println!("代码块执行时间: {duration:?}");
        }
    };
}

/// 使用 `$meta` 匹配元数据
macro_rules! with_attribute {
    (#[$meta:meta] $item:item) => {
        #[$meta]
        $item
    };
}

/// 使用 `$literal` 匹配字面量
macro_rules! print_literal {
    ($l:literal) => {
        println!("字面量: {l}", l = $l);
    };
}

/// 主演示函数
pub fn demonstrate_declarative_macros() {
    println!("=== 声明宏示例 ===");

    // 1. 基础声明宏
    say_hello!();

    // 2. 带参数的声明宏
    greet!("Rust");

    // 3. 多个匹配臂的声明宏
    create_function!(my_function);
    my_function();

    // 4. 重复模式的声明宏
    let v = vec_with_repeat![1, 2, 3, 4, 5];
    println!("自定义 vec 宏: {v:?}");

    // 5. 复杂的声明宏示例
    my_println!();
    my_println!("自定义 println 宏: {}", "Hello, Macro!");

    // 6. 不同类型参数的声明宏
    my_assert_equal!(2 + 2, 4);
    println!("断言通过: 2 + 2 == 4");

    // 7. DSL 示例
    calculate! {
        eval 1 + 2
    }

    calculate! {
        eval 3 * 4
    }

    // 8. 各种宏指示符的用法示例
    create_variable!(my_var, 42);

    let _default_i32 = default_value!(i32);
    let _default_string = default_value!(String);

    match_pattern!(Some(5), Some(_x));

    fn dummy_function() -> i32 {
        42
    }
    call_function!(dummy_function);

    define_item! {
        struct MyStruct {
            value: i32,
        }
    }

    define_struct_with_visibility! {
        pub MyPublicStruct {
            pub field1: i32,
            field2: String
        }
    }

    echo_tokens!(println!("Hello, world!"));

    time_block!({
        std::thread::sleep(std::time::Duration::from_millis(100));
    });

    with_attribute! {
        #[derive(Debug)]
        struct AttributedStruct {
            value: i32,
        }
    }

    print_literal!(42);
    print_literal!("Hello, world!");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_declarative_macros() {
        demonstrate_declarative_macros();
    }

    #[test]
    fn test_vec_with_repeat() {
        let v = vec_with_repeat![1, 2, 3];
        assert_eq!(v, vec![1, 2, 3]);
    }

    #[test]
    fn test_my_assert_equal() {
        my_assert_equal!(1, 1);
    }

    #[test]
    #[should_panic(expected = "断言失败")]
    fn test_my_assert_equal_panic() {
        my_assert_equal!(1, 2);
    }

    #[test]
    fn test_create_variable() {
        create_variable!(test_var, "test");
    }

    #[test]
    fn test_default_value() {
        let _val: i32 = default_value!(i32);
        let _val: String = default_value!(String);
    }

    #[test]
    fn test_match_pattern() {
        match_pattern!(Some(5), Some(_x));
    }

    #[test]
    fn test_print_literal() {
        print_literal!(42);
        print_literal!("test");
    }
}
